#![no_std]
#![feature(test)]
#[cfg(target_arch = "x86_64")]
extern crate test;

mod bits_index;
mod bits_iter;
mod bits_ops;

pub mod field;

use core::ops::{BitAndAssign, BitOrAssign, Not, RangeInclusive};

pub use bits_index::*;
pub use bits_iter::*;
pub use bits_ops::*;

/// 将整型转为 Bits，实际操作由 BitsOps 来实现。
pub trait IntoBits
where
    Self: Sized + Copy,
{
    type Output: BitsOps<Self>;
    fn bits<T: BitIndex>(self, range: T) -> Self::Output;
    fn bitmask(self, mask: Self) -> BitMask<Self> {
        BitMask { mask, value: self }
    }
}

macro_rules! impl_intobits {
    ($($Type:ty) *) => {
        $(impl IntoBits for $Type {
            type Output = Bits<Self>;

            fn bits<T: BitIndex>(self, range:T) -> Bits<Self>{
                let upper = match  <T as BitIndex>::upper(&range) {
                    core::ops::Bound::Unbounded => <$Type>::BITS - 1,
                    core::ops::Bound::Included(v) => *v,
                    core::ops::Bound::Excluded(v) => *v - 1,
                };
                let low = match  <T as BitIndex>::low(&range) {
                    core::ops::Bound::Unbounded => 0,
                    core::ops::Bound::Included(v) => *v,
                    core::ops::Bound::Excluded(v) => *v,
                };

                Bits {
                    value: self,
                    range: low ..= upper
                }
            }
        })*
    };
}

impl_intobits!(u8 u16 u32 u64 u128 usize);

/// 该结构体可以通过 `0x10u32.bits(0x01)` 来构造
/// ```
/// use bits::BitsOps;
/// use bits::IntoBits;
/// assert_eq!(0u8.bits(0).set(), 0x01);
/// assert_eq!(0u8.bits(1).set(), 0x02);
/// assert_eq!(0u8.bits(4..=7).set(), 0xf0);
/// assert_eq!(0xffu8.bits(4..=7).clr(), 0x0f);
/// assert_eq!(0xffu8.bits(3).revert(), 0xf7);
/// assert_eq!(0xffu8.bits(4..=7).revert(), 0x0f);
/// assert_eq!(0u8.bits(4..=7).write(0x10), 0x0);
/// // 只会写入 value 的相应的 bit 位。低 4 bit 并不会被修改。
/// assert_eq!(0u8.bits(4..=7).write(0x12), 0x20);
/// assert_eq!(0x12u8.bits(4..=7).read(), 0x1);
/// assert_eq!(0xf0u8.bits(4..=7).is_set(), true);
/// assert_eq!(0x70u8.bits(4..=7).is_set(), false);
/// assert_eq!(0x70u8.bits(4..=7).is_clr(), false);
/// assert_eq!(0x70u8.bits(0..=3).is_clr(), true);
/// ```
/// 单独构造该结构体主要是为了将 bit range 和要写入的值分开，这两者的类型可能会一样，在无 IDE 类型提示的情况下导致调用顺序颠倒：
/// `0u8.bits_write(5, 1)` 无法区分哪一个是 range，哪一个是要写入的值。
///
/// 当然也可以通过 `0u8.bits_set(5); ` 来避免，但 bits_write 的存在依旧会暴露风险。
///
/// 综上选择单独构造 Bits 结构体。
///
/// ## 关于溢出
///
/// 只尽可能的使输出的值符合预期：
/// `0u8.bits(0..=10).set() == 0xff` `0xffu8.bits(3..2).clr() == 0xff`
/// 当然这两个代码片段在非 release 编译下会导致溢出 panic（rust 自带的溢出检查）。
pub struct Bits<V: IntoBits> {
    pub range: RangeInclusive<u32>,
    value: V,
}

impl<V: IntoBits> IntoIterator for Bits<V> {
    type Item = Bit<V>;

    type IntoIter = bits_iter::BitsIter<V>;

    fn into_iter(self) -> Self::IntoIter {
        Self::IntoIter {
            low: *self.range.start(),
            upper: *self.range.end(),
            value: self.value,
        }
    }
}

pub struct BitMask<T> {
    mask: T,
    value: T,
}
impl<T> BitMask<T>
where
    T: Copy + BitOrAssign,
{
    #[must_use]
    pub fn set(&self) -> T {
        let mut ret = self.value;
        ret |= self.mask;
        ret
    }
}
impl<T> BitMask<T>
where
    T: Copy + Not + BitAndAssign<<T as Not>::Output>,
{
    #[must_use]
    pub fn clr(&self) -> T {
        let mut ret = self.value;
        ret &= !self.mask;
        ret
    }
}

pub struct Bit<V: IntoBits> {
    value: V,
}
impl<V: IntoBits> Bit<V> {
    #[inline]
    pub fn is_set(&self) -> bool {
        self.value.bits(0).is_set()
    }
    #[inline]
    pub fn is_clr(&self) -> bool {
        !self.is_set()
    }
}

pub const fn read_bits_u32(val: u32, range: RangeInclusive<u32>) -> u32 {
    let low = *range.start();
    let upper = *range.end();
    let mask = ((1u32 << upper) - (1u32 << low)) | (1 << upper);
    (mask & val) >> low
}

pub const fn write_bits_u32(val: u32, range: RangeInclusive<u32>, val2: u32) -> u32 {
    let low = *range.start();
    let upper = *range.end();
    let low_effect_bits = upper - low + 1;
    let upper_bits = u32::BITS - low_effect_bits;
    // 移除掉冗余数据，防止有脏数据
    let val_to_write = (val2 << upper_bits) >> upper_bits;
    let mask = ((1u32 << upper) - (1u32 << low)) | (1 << upper);
    (!mask & val) | (val_to_write << low)
}

#[cfg(all(test, target_arch = "x86_64"))]
mod tests {
    use test::Bencher;

    use crate::{read_bits_u32, write_bits_u32, BitsOps, IntoBits};
    #[test]
    fn read_bits_u32_test() {
        assert_eq!(read_bits_u32(0x55aa55aa, 0..=7), 0xaa);
    }
    #[test]
    fn write_bits_u32_test() {
        assert_eq!(write_bits_u32(0x55aa55aa, 0..=7, 0xff), 0x55aa55ff);
    }
    #[test]
    fn bits_ops_test() {
        assert_eq!(0xffu8.bits(..).clr(), 0);
        assert_eq!(0xffu8.bits(..1).clr(), 0xff - 0b1);
        assert_eq!(0xffu8.bits(1..).clr(), 1);
        assert_eq!(0xffu8.bits(1..2).clr(), 0xff - 0b10);
        assert_eq!(0xffu8.bits(1..=2).clr(), 0xff - 0b110);
        assert_eq!(0xffu8.bits(..).msb(), true);
        assert_eq!(0x70u8.bits(4..=5).msb(), true);
        assert_eq!(0x7fu8.bits(..).msb(), false);
        assert_eq!(0x70u8.bits(4..=7).lsb(), true);
    }

    #[test]
    #[should_panic(expected = "overflow")]
    fn bits_ops_test_end_overflow() {
        {
            0xffu8.bits(0..=8).clr()
        };
    }
    #[test]
    #[should_panic(expected = "overflow")]
    fn bits_ops_test_start_overflow() {
        {
            0xffu8.bits(2..=1).clr()
        };
    }
    #[no_mangle]
    fn bits_iterator(data: u64, out: &mut [u8; 64]) {
        for (idx, bit) in data.bits(0..=63).into_iter().enumerate() {
            out[idx] = bit.is_set() as u8;
        }
    }
    #[no_mangle]
    fn plain_loop(data: u64, out: &mut [u8; 64]) {
        let mut mask = 0x1u64;
        let mut idx = 0usize;
        while idx < 64 {
            if data & mask != 0 {
                out[idx] = 1;
            } else {
                out[idx] = 0;
            }
            mask <<= 1;
            idx += 1;
        }
    }

    #[test]
    fn bits_iterator_test() {
        let mut out_iterator = [0u8; 64];
        let mut out_loop = [0u8; 64];
        (0..=0xffff).for_each(|x| {
            bits_iterator(x, &mut out_iterator);
            plain_loop(x, &mut out_loop);
            assert_eq!(out_iterator, out_loop);
        })
    }
    #[test]
    // TODO 需要随机测试
    fn count_ones_test() {
        (0..=0x7f).for_each(|x: u8| assert_eq!(x.bits(..).count_ones(), x.count_ones()));
        (0x5a5a..=0xffff).for_each(|x: u16| assert_eq!(x.bits(..).count_ones(), x.count_ones()));
        (0x5a5a5a5a..=0x5a5aff5a)
            .for_each(|x: u32| assert_eq!(x.bits(..).count_ones(), x.count_ones()));
        (0x5a5a_5a5a_5a5a_5a5a..=0x5a5a_55aa_ffff_5a5a)
            .for_each(|x: u64| assert_eq!(x.bits(..).count_ones(), x.count_ones()));
    }

    #[bench]
    fn bench_plain_loop_code(b: &mut Bencher) {
        let n = test::black_box(0xffff);
        let mut out = test::black_box([0u8; 64]);
        b.iter(|| (0..=n).for_each(|x| plain_loop(x, &mut out)))
    }

    #[bench]
    fn bench_bits_iterator_code(b: &mut Bencher) {
        let n = test::black_box(0xffff);
        let mut out = test::black_box([0u8; 64]);
        b.iter(|| (0..=n).for_each(|x| bits_iterator(x, &mut out)))
    }
    #[no_mangle]
    fn count_ones_bits(data: u64) -> u32 {
        data.bits(..).count_ones()
    }
    #[no_mangle]
    fn count_ones_interal(data: u64) -> u32 {
        data.count_ones()
    }
    #[bench]
    fn bench_count_ones_bits(b: &mut Bencher) {
        let n = test::black_box(0xffff);
        let mut result = test::black_box(0);
        b.iter(|| {
            (0..=n).for_each(|x: u16| {
                result += x.bits(0..=15).count_ones();
            })
        });
    }
    #[bench]
    fn bench_count_ones_internal(b: &mut Bencher) {
        let n = test::black_box(0xffff);
        let mut result = test::black_box(0);
        b.iter(|| {
            (0..=n).for_each(|x: u16| {
                result += x.count_ones();
            })
        })
    }
}

// 👌 请注意对比和修改测试跑分结果
//
// test tests::bench_bits_iterator_code  ... bench:      15,323 ns/iter (+/- 172)
// test tests::bench_count_ones_bits     ... bench:      26,211 ns/iter (+/- 326)
// test tests::bench_count_ones_internal ... bench:      28,036 ns/iter (+/- 494)
// test tests::bench_plain_loop_code     ... bench:   1,514,810 ns/iter (+/- 13,509)
